//电梯调度系统
//运行环境：http://play.elevatorsaga.com/
//源码下载地址：https://github.com/magwo/elevatorsaga
//在index.html的最后调用此脚本替换原来的函数
"use strict"

//为了方便调试，将这些参数作为全局属性
var waitQueue=[];

var system={
    init: function(elevators, floors) {
        window.elevators=elevators;
        window.floors=floors;

        /*监听事件*/
        floors.forEach(function (floor,floorNum){
            //floor.floorNum()
            floor.wait={"up":false,"down":false};
            floor.elevator={"up":false,"down":false};
            floor.on("up_button_pressed", function() {
                console.group("up_button_pressed");
                findElevator(this,"up");
                console.groupEnd("up_button_pressed");
            });
            floor.on("down_button_pressed", function() {
                console.group("down_button_pressed");
                findElevator(this,"down");
                console.groupEnd("down_button_pressed");
            });
        });
        elevators.forEach(function(elevator,index){
            // elevator.goToFloor(3);
            // elevator.goToFloor(2, true);
            // elevator.stop();
            // elevator.currentFloor();
            // elevator.goingUpIndicator();
            // elevator.goingDownIndicator();
            // elevator.maxPassengerCount();
            // elevator.loadFactor();
            // elevator.destinationDirection();
            // elevator.destinationQueue = [];
            // elevator.checkDestinationQueue();
            // elevator.getPressedFloors();
            elevator.keepMoving="stopped";
            elevator.group = index%3*2;
            elevator.on("idle", function() {
                this.goToFloor(index*2);
                console.group("idle");
                autoRun(this);
                console.groupEnd("idle");
            });
            elevator.on("floor_button_pressed", function(floorNum) {
                console.group("floor_button_pressed");
                replanDestination(this);
                //insertDestination(this,floorNum);
                console.groupEnd("floor_button_pressed");
            });
            elevator.on("passing_floor", function(floorNum, direction) {
                console.group("passing_floor",floorNum);
                //如果电梯跑的太快，会直接跳过应该停的楼层，所以需要调用其他电梯
                missDestination(this,floorNum);
                console.groupEnd("passing_floor");
            });
            elevator.on("stopped_at_floor", function(floorNum) {
                console.group("stopped_at_floor");
                stopAtDestination(this,floorNum);
                console.groupEnd("stopped_at_floor");
            });
        });

        //重置所有计划
        function globalReset(){

        }
        //楼层:查找最近的电梯，并且请求停靠
        function findElevator(floor,direction){
            floor.wait[direction]=true;
            var floorNum=floor.floorNum();
            console.log("findElevator",floorNum,direction);
            var _elevator=null,minDistance=floors.length;
            for(var i=0;i<elevators.length;i++){
                var elevator=elevators[i];
                var current=elevator.currentFloor();
                var keepMoving=elevator.keepMoving;
                var isCan=elevator.loadFactor()<0.9;
                var isSameDirection=(keepMoving==="up"&&current<=floorNum)||(keepMoving==="down"&&current>=floorNum);
                if(isCan&&isSameDirection){
                    var distance=Math.abs(floorNum-current);
                    if(distance<minDistance){
                        minDistance=distance;
                        _elevator=elevator;
                    }
                }
            }
            if(_elevator){
                floor.elevator[direction]=_elevator;
                if(_elevator.keepMoving==="stopped"){
                    autoRun(_elevator);
                }
            }

        }
        //电梯:自动运行
        function autoRun(elevator){
            if(elevator.keepMoving!=="down"){
                elevator.keepMoving="up";
            }
            if(elevator.destinationQueue.length===0){
                replanDestination(elevator);
            }
            elevator.keepMoving=elevator.keepMoving==="up"?"down":"up";
            if(elevator.destinationQueue.length===0){
                replanDestination(elevator);
            }
            console.log("autoRun",elevator.destinationQueue);
            if(elevator.destinationQueue.length===0){
                elevator.keepMoving="stopped"
            }
            else{
                elevator.checkDestinationQueue();
            }
        }
        //电梯:重新规划停靠线路
        function replanDestination2(elevator){
            var keepMoving=elevator.keepMoving;
            if(keepMoving==="stopped"){
                autoRun(elevator);
            }
            var isCan=elevator.loadFactor()>0.8;
            var current=elevator.currentFloor();
            var pressed=elevator.getPressedFloors();
            var pressedFloors=new Array(floors.length);
            var queue=[];
            console.log("replanDestination",keepMoving,current,pressed);
            for(var i=0;i<pressed.length;i++){
                pressedFloors[pressed[i]]=true;
            }
            var backFloor=-1;
            var isUp=floors[i].wait["up"]===true&&floors[i].elevator["up"]===elevator;
            var isDown=floors[i].wait["down"]===true&&floors[i].elevator["down"]===elevator;
            if(keepMoving==="up"){
                var backFloor=-1;
                for(var i=current;i<floors.length;i++){
                    if(pressedFloors[i]===true){
                        queue.push(i);
                        break;
                    }
                    else if(isCan){
                        if(isUp){
                            queue.push(i);
                            break;
                        }
                        if(isDown&&i>backFloor){
                            backFloor=i;
                        }
                    }
                }
                if((queue.length===0&&backFloor>-1)){
                    queue.push(backFloor);
                }
            }
            else{
                var backFloor=floors.length;
                for(var i=current;i>=0;i--){
                    if(isDown||pressedFloors[i]===true){
                        queue.push(i);
                        break;
                    }
                    if(isUp&&i<backFloor){
                        backFloor=i;
                    }
                }
                if((queue.length===0&&backFloor<floors.length)){
                    queue.push(backFloor);
                }
            }
            if(queue.length===0){
                var goingUp=true;
                var goingDown=true;
            }
            else if(queue[0]>current){
                var goingUp=true;
                var goingDown=false;
            }
            else if(queue[0]<current){
                var goingUp=false;
                var goingDown=true;
            }
            elevator.goingUpIndicator(goingUp);
            elevator.goingDownIndicator(goingDown);
            elevator.destinationQueue=queue;
        }
        function replanDestination(elevator){
            var keepMoving=elevator.keepMoving;
            if(keepMoving==="stopped"){
                autoRun(elevator);
            }
            var current=elevator.currentFloor();
            var pressed=elevator.getPressedFloors();
            var pressedFloors=new Array(floors.length);
            var queue=[];
            console.log("replanDestination",keepMoving,current,pressed);
            for(var i=0;i<pressed.length;i++){
                pressedFloors[pressed[i]]=true;
            }
            var backFloor=-1;
            if(keepMoving==="up"){
                var backFloor=-1;
                for(var i=current;i<floors.length;i++){
                    if((floors[i].wait["up"]===true)||pressedFloors[i]===true){
                        queue.push(i);
                    }
                    if(floors[i].wait["down"]===true&&i>backFloor){
                        backFloor=i;
                    }
                }
                if((queue.length===0&&backFloor>-1)||backFloor>queue[queue.length-1]){
                    queue.push(backFloor);
                }
            }
            else{
                var backFloor=floors.length;
                for(var i=current;i>=0;i--){
                    if((floors[i].wait["down"]===true)||pressedFloors[i]===true){
                        queue.push(i);
                    }
                    if(floors[i].wait["up"]===true&&i<backFloor){
                        backFloor=i;
                    }
                }
                if((queue.length===0&&backFloor<floors.length)||backFloor<queue[queue.length-1]){
                    queue.push(backFloor);
                }
            }
            if(queue.length===0){
                var goingUp=true;
                var goingDown=true;
            }
            else if(queue[0]>current){
                var goingUp=true;
                var goingDown=false;
            }
            else if(queue[0]<current){
                var goingUp=false;
                var goingDown=true;
            }
            elevator.goingUpIndicator(goingUp);
            elevator.goingDownIndicator(goingDown);
            elevator.destinationQueue=queue;
        }
        //电梯:在停靠点停靠
        function stopAtDestination(elevator,floorNum){
            var queue=elevator.destinationQueue;
            if(queue.length===0){
                var goingUp=true;
                var goingDown=true;
            }
            else{
                var goingUp=elevator.goingUpIndicator();
                var goingDown=elevator.goingDownIndicator();
            }
            
            var floor=floors[floorNum];
            if(goingUp){
                floor.wait.up=false;
                floor.elevator.up=false;
            }
            if(goingDown){
                floor.wait.down=false;
                floor.elevator.down=false;
            }
            replanDestination(elevator);
            //elevator.checkDestinationQueue();
        }
        //电梯:错过停靠点
        function missDestination(elevator,floorNum){

            // var floor=floors[floorNum];
            // if(goingUp){
            //     if(floor.elevator.up===elevator){
            //         floor.elevator.up=false;
            //         findElevator(floor,direction);
            //     }
            // }
            // if(goingDown){
            //     if(floor.elevator.down===elevator){
            //         floor.elevator.down=false;
            //     }
            // }
        }
        window.echo=function(){
            console.log("floors","wait_up","wait_down","elevator_up","elevator_down");
            for(var i=0;i<floors.length;i++){
                var floor=floors[i];
                console.log(floor.wait.up,floor.wait.down,floor.elevator.up,floor.elevator.down);
            }

            console.log("elevator","pressed","queue","keepMoving");
            for(var i=0;i<elevators.length;i++){
                var elevator=elevators[i];
                console.log(elevator.getPressedFloors(),elevator.destinationQueue,elevator.keepMoving);
            }
        }
    },
    update: function(dt, elevators, floors) {
    }
}
var getCodeObjFromCode = function(code) {
    return system;
}
//replan:全局,清空所有规划,先按楼层分配,然后各电梯重新规划路线;楼层,重新计算最近的电梯并且发送停靠请求;电梯,重新计算停靠计划